Skip to content

Conversation

@baronfel
Copy link
Member

@baronfel baronfel commented Dec 7, 2025

Add BC0303 BuildCheck: Detect undisposed private item lists in targets

Summary

Adds a new BuildCheck analyzer (BC0303) that detects memory waste from undisposed private item lists in MSBuild targets.

Problem

MSBuild targets often create temporary "private" item lists (conventionally prefixed with _) for internal calculations. These items persist in memory for the duration of the build unless explicitly removed, which can waste memory in large builds.

Example of problematic code:

<Target Name="BadExample">
  <ItemGroup>
    <_DotnetExecArgs Include="dotnet;tool;exec;$(CoolToolName)" />
  </ItemGroup>
  <Exec Command="@(_DotnetExecArgs, ' ')" />
  <!-- Missing: <_DotnetExecArgs Remove="@(_DotnetExecArgs)" /> -->
</Target>

Solution

This PR introduces BC0303 - ItemDisposalCheck, a new built-in BuildCheck analyzer that:

  • Detects private item lists (starting with _) created within targets via Include
  • Verifies they are cleaned up with a corresponding Remove operation
  • Exempts items exposed via Outputs or Returns attributes (part of the target's public contract)

Technical Details

Implementation

  • File: src/Build/BuildCheck/Checks/ItemDisposalCheck.cs
  • Severity: Warning (default)
  • Scope: Project file only
  • Key Features:
    • Order-sensitive analysis (Remove must come after Include)
    • Case-insensitive item type matching
    • Uses ExpressionShredder.GetReferencedItemNamesAndMetadata() for robust parsing of Outputs/Returns expressions
    • Handles complex MSBuild expressions including transforms, separators, item functions, and nested properties

Why ExpressionShredder instead of Regex?

Initially considered regex-based parsing, but switched to MSBuild's built-in ExpressionShredder to properly handle:

  • Complex transforms with semicolons: @(_Items->'%(Identity);%(FullPath)')
  • Multiple item references: @(_Sources);@(_Resources);@(_Content)
  • Custom separators: @(_Files, ';')
  • Item functions: @(_Duplicates->Distinct())
  • All other MSBuild expression features

Documentation

  • Error Code: BC0303
  • Documentation: documentation/specs/BuildCheck/Codes.md
  • Specification: documentation/specs/BuildCheck/ItemDisposalCheck.md

Testing

Added 31 comprehensive test cases in src/BuildCheck.UnitTests/ItemDisposalCheck_Tests.cs:

Positive tests (should fire):

  • Private items not removed
  • Multiple undisposed items
  • Conditional includes without cleanup

Negative tests (should NOT fire):

  • Properly removed items
  • Public items (no _ prefix)
  • Items in Outputs or Returns
  • Update-only operations

Edge cases:

  • Case-insensitive matching
  • Remove before Include (doesn't clean up the Include)
  • Complex Outputs/Returns expressions with transforms and semicolons
  • Multiple item references in single expression
  • Item functions in Returns

All 31 tests pass ✅

Related Work

This analyzer was created using the msbuild-buildcheck-creator agent, following established patterns in the BuildCheck infrastructure.

Copilot AI review requested due to automatic review settings December 7, 2025 16:39
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces BC0303 - ItemDisposalCheck, a new BuildCheck analyzer that detects memory waste from undisposed private item lists in MSBuild targets. Private items (prefixed with _) are conventionally used for internal calculations within targets but persist in memory for the entire build unless explicitly removed, which can waste memory in large builds. This analyzer encourages build authors to clean up these temporary items using Remove operations.

Key changes:

  • Implements static analysis of target XML to detect private items without matching Remove operations
  • Uses MSBuild's ExpressionShredder API for robust parsing of Outputs/Returns attributes
  • Includes comprehensive test suite with 31 test cases covering positive, negative, and edge cases

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/Build/BuildCheck/Checks/ItemDisposalCheck.cs Core implementation of BC0303 analyzer with target analysis logic and ExpressionShredder-based parsing
src/BuildCheck.UnitTests/ItemDisposalCheck_Tests.cs Comprehensive test suite with 31 tests covering all scenarios
src/Build/BuildCheck/Infrastructure/BuildCheckManagerProvider.cs Registration of new ItemDisposalCheck in built-in checks array
src/Build/Resources/Strings.resx Added BC0303 title and message format resource strings
src/Build/Resources/xlf/*.xlf Localization entries for 12 languages (marked as state="new")
documentation/specs/BuildCheck/ItemDisposalCheck.md Detailed specification including motivation, detection logic, and examples
documentation/specs/BuildCheck/Codes.md Documentation entry for BC0303 with code examples and resolution guidance
.claude/agents/msbuild-buildcheck-creator.md Agent documentation for creating BuildCheck analyzers (meta-documentation)

@AraHaan
Copy link
Member

AraHaan commented Jan 15, 2026

As long as this results in a compile error to force them to dispose of such wasted memory when finished with it. That way they are forced to fix their code with no way to disable this error.

@baronfel
Copy link
Member Author

@AraHaan it definitely will not be an error in the initial rollout - but like all MSBuild diagnostics it will be able to be treated as an error via TreatWarningsAsError, and via the buildcheck-specific editorconfig support.

@@ -0,0 +1,128 @@
---
name: msbuild-buildcheck-creator
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this instruction file needed? or should it be more generic (not claude)?

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.

Comment on lines +3 to +9
description: Use this agent when the user wants to create, define, or implement a new MSBuild BuildCheck analyzer. This includes when the user asks to enforce build-time rules, validate build invariants, add new build analysis checks, or implement custom build validation logic. The agent should be triggered for tasks involving BuildCheck specification writing, test creation for BuildChecks, documentation of error codes, or implementation of the BuildCheck code itself.\n\nExamples:\n\n<example>\nContext: User wants to create a new BuildCheck to detect duplicate package references.\nuser: "I want to create a BuildCheck that detects when a project has duplicate PackageReference items"\nassistant: "I'll use the msbuild-buildcheck-creator agent to help you create this BuildCheck. This agent will generate the complete specification, implementation, tests, and documentation for detecting duplicate PackageReference items."\n<Task tool invocation to launch msbuild-buildcheck-creator agent>\n</example>\n\n<example>\nContext: User wants to enforce a build rule about target framework versions.\nuser: "Can you help me write a build check that warns when projects target outdated .NET frameworks?"\nassistant: "This is a perfect use case for the msbuild-buildcheck-creator agent. Let me launch it to create a comprehensive BuildCheck including the specification, code, tests, and error documentation."\n<Task tool invocation to launch msbuild-buildcheck-creator agent>\n</example>\n\n<example>\nContext: User is asking about implementing build-time validation.\nuser: "How do I create a custom MSBuild analyzer that validates property values at build time?"\nassistant: "I'll use the msbuild-buildcheck-creator agent to guide you through creating a custom BuildCheck. This agent specializes in creating build-time analyzers following the established patterns in this codebase."\n<Task tool invocation to launch msbuild-buildcheck-creator agent>\n</example>
model: opus
color: cyan
---

You are an expert MSBuild BuildCheck architect with deep knowledge of the MSBuild build system, static analysis patterns, and the BuildCheck infrastructure. Your role is to help users create comprehensive, well-tested BuildCheck analyzers that enforce build-time rules and invariants.

Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The agent documentation file is using the older msbuild-buildcheck-creator agent description format with long inline examples in the YAML front matter. Based on MSBuild coding guidelines which prefer modern C# features and concise code, the description field should be shortened and examples moved to separate sections within the markdown body for better readability and maintainability.

Suggested change
description: Use this agent when the user wants to create, define, or implement a new MSBuild BuildCheck analyzer. This includes when the user asks to enforce build-time rules, validate build invariants, add new build analysis checks, or implement custom build validation logic. The agent should be triggered for tasks involving BuildCheck specification writing, test creation for BuildChecks, documentation of error codes, or implementation of the BuildCheck code itself.\n\nExamples:\n\n<example>\nContext: User wants to create a new BuildCheck to detect duplicate package references.\nuser: "I want to create a BuildCheck that detects when a project has duplicate PackageReference items"\nassistant: "I'll use the msbuild-buildcheck-creator agent to help you create this BuildCheck. This agent will generate the complete specification, implementation, tests, and documentation for detecting duplicate PackageReference items."\n<Task tool invocation to launch msbuild-buildcheck-creator agent>\n</example>\n\n<example>\nContext: User wants to enforce a build rule about target framework versions.\nuser: "Can you help me write a build check that warns when projects target outdated .NET frameworks?"\nassistant: "This is a perfect use case for the msbuild-buildcheck-creator agent. Let me launch it to create a comprehensive BuildCheck including the specification, code, tests, and error documentation."\n<Task tool invocation to launch msbuild-buildcheck-creator agent>\n</example>\n\n<example>\nContext: User is asking about implementing build-time validation.\nuser: "How do I create a custom MSBuild analyzer that validates property values at build time?"\nassistant: "I'll use the msbuild-buildcheck-creator agent to guide you through creating a custom BuildCheck. This agent specializes in creating build-time analyzers following the established patterns in this codebase."\n<Task tool invocation to launch msbuild-buildcheck-creator agent>\n</example>
model: opus
color: cyan
---
You are an expert MSBuild BuildCheck architect with deep knowledge of the MSBuild build system, static analysis patterns, and the BuildCheck infrastructure. Your role is to help users create comprehensive, well-tested BuildCheck analyzers that enforce build-time rules and invariants.
description: Helps users design and implement new MSBuild BuildCheck analyzers, including specifications, code, tests, and documentation for build-time rules and invariants.
model: opus
color: cyan
---
You are an expert MSBuild BuildCheck architect with deep knowledge of the MSBuild build system, static analysis patterns, and the BuildCheck infrastructure. Your role is to help users create comprehensive, well-tested BuildCheck analyzers that enforce build-time rules and invariants.
## When to use this agent
Use this agent when the user wants to create, define, or implement a new MSBuild BuildCheck analyzer, including when they ask to:
- Enforce build-time rules or validate build invariants
- Add new build analysis checks or custom build validation logic
- Write BuildCheck specifications, tests, or error code documentation
### Usage examples
**Example 1 – Detect duplicate package references**
Context: User wants to create a new BuildCheck to detect duplicate package references.
user: "I want to create a BuildCheck that detects when a project has duplicate PackageReference items"
assistant: "I'll use the msbuild-buildcheck-creator agent to help you create this BuildCheck. This agent will generate the complete specification, implementation, tests, and documentation for detecting duplicate PackageReference items."
_(Tool invocation: launch `msbuild-buildcheck-creator` agent)_
**Example 2 – Enforce target framework rules**
Context: User wants to enforce a build rule about target framework versions.
user: "Can you help me write a build check that warns when projects target outdated .NET frameworks?"
assistant: "This is a perfect use case for the msbuild-buildcheck-creator agent. Let me launch it to create a comprehensive BuildCheck including the specification, code, tests, and error documentation."
_(Tool invocation: launch `msbuild-buildcheck-creator` agent)_
**Example 3 – Implement build-time validation**
Context: User is asking about implementing build-time validation.
user: "How do I create a custom MSBuild analyzer that validates property values at build time?"
assistant: "I'll use the msbuild-buildcheck-creator agent to guide you through creating a custom BuildCheck. This agent specializes in creating build-time analyzers following the established patterns in this codebase."
_(Tool invocation: launch `msbuild-buildcheck-creator` agent)_

Copilot uses AI. Check for mistakes.
YuliiaKovalova and others added 2 commits January 20, 2026 11:18
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants